Skip to main content

compio_driver\sys\driver\iocp/
op.rs

1use super::*;
2/// Abstraction of IOCP operations.
3///
4/// # Safety
5///
6/// Implementors must ensure that the operation is safe to be polled
7/// according to the returned [`OpType`].
8pub unsafe trait OpCode {
9    /// Type that contains self-references and other needed info during the
10    /// operation
11    type Control: Default;
12
13    /// Initialize the control
14    ///
15    /// # Safety
16    ///
17    /// Caller must guarantee that during the lifetime of `ctrl`, `Self` is
18    /// unmoved and valid.
19    unsafe fn init(&mut self, _: &mut Self::Control) {}
20
21    /// Determines that the operation is really overlapped defined by
22    /// Windows API. If not, the driver will try to operate it in
23    /// another thread.
24    fn op_type(&self, control: &Self::Control) -> OpType {
25        _ = control;
26        OpType::Overlapped
27    }
28
29    /// Perform Windows API call with given pointer to overlapped struct.
30    ///
31    /// It is always safe to cast `optr` to a pointer to
32    /// [`Overlapped<Self>`].
33    ///
34    /// Don't do heavy work here if [`OpCode::op_type`] returns
35    /// [`OpType::Event`].
36    ///
37    /// # Safety
38    ///
39    /// * `self` must be alive until the operation completes.
40    /// * When [`OpCode::op_type`] returns [`OpType::Blocking`], this method is
41    ///   called in another thread.
42    unsafe fn operate(
43        &mut self,
44        control: &mut Self::Control,
45        optr: *mut OVERLAPPED,
46    ) -> Poll<io::Result<usize>>;
47
48    /// Cancel the async IO operation.
49    ///
50    /// Usually it calls `CancelIoEx`.
51    // # Safety for implementors
52    //
53    // `optr` must not be dereferenced. It's only used as a marker to identify the
54    // operation.
55    fn cancel(&mut self, control: &mut Self::Control, optr: *mut OVERLAPPED) -> io::Result<()> {
56        _ = control;
57        _ = optr;
58        Ok(())
59    }
60
61    /// Set the result when it completes.
62    /// The operation stores the result and is responsible to release it if
63    /// the operation is cancelled.
64    ///
65    /// # Safety
66    ///
67    /// The params must be the result coming from this operation.
68    unsafe fn set_result(
69        &mut self,
70        _: &mut Self::Control,
71        _: &io::Result<usize>,
72        _: &crate::Extra,
73    ) {
74    }
75}
76
77pub(crate) trait Carry {
78    fn op_type(&self) -> OpType;
79
80    unsafe fn operate(&mut self, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>>;
81
82    fn cancel(&mut self, optr: *mut OVERLAPPED) -> io::Result<()>;
83
84    unsafe fn set_result(&mut self, _: &io::Result<usize>, _: &crate::Extra);
85}
86
87impl<T: OpCode> Carry for Carrier<T> {
88    fn op_type(&self) -> OpType {
89        let (op, control) = self.as_iocp();
90        op.op_type(control)
91    }
92
93    unsafe fn operate(&mut self, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
94        let (op, control) = self.as_iocp_mut();
95        unsafe { op.operate(control, optr) }
96    }
97
98    fn cancel(&mut self, optr: *mut OVERLAPPED) -> io::Result<()> {
99        let (op, control) = self.as_iocp_mut();
100        op.cancel(control, optr)
101    }
102
103    unsafe fn set_result(&mut self, res: &io::Result<usize>, extra: &crate::Extra) {
104        let (op, control) = self.as_iocp_mut();
105        unsafe { op.set_result(control, res, extra) }
106    }
107}